<template>
  <a-drawer width="30%" placement="left" v-model:visible="isShow" :closable="true" @close="onClose">
    <a-descriptions title="基本信息" :column="2" layout="" :bordered="true" size="small"
      :labelStyle="{width:'100px', textAlign: 'right'}">
      <a-descriptions-item label="名称" :span="2">
        {{form.name}}
      </a-descriptions-item>
      <a-descriptions-item label="种子名称" :span="2">
        {{form.btname}}
      </a-descriptions-item>
      <a-descriptions-item label="添加时间" :span="2">
        {{formatDate(form.addtime)}}
      </a-descriptions-item>
      <a-descriptions-item label="种子文件" :span="2">
        <a-space>
          {{form.torrentFile}}
          <a-button v-if="form.torrentFile" shape="circle" size="small" @click="downloadTorrentFile(form.torrentFile)"
            :loading="downloading">
            <template #icon>
              <DownloadOutlined />
            </template>
          </a-button>
        </a-space>
      </a-descriptions-item>
      <a-descriptions-item label="下载链接" :span="2">
        {{form.address}}
      </a-descriptions-item>
      <a-descriptions-item label="所属分类" :span="2">
        {{form.categoryName}}
      </a-descriptions-item>
      <a-descriptions-item label="所属站点" :span="2">
        {{form.siteName}}
      </a-descriptions-item>
      <a-descriptions-item label="描述" :span="2">
        {{form.description}}
      </a-descriptions-item>
      <a-descriptions-item label="TMDB ID" :span="2">
        {{ form.tmdbid == 0 ? '无法识别' : (form.tmdbid==-1?'多结果':form.tmdbid) }}
        <a-button shape="round" size="small" @click="toRecognize">
          识别
        </a-button>
      </a-descriptions-item>
      <a-descriptions-item v-if="form.mediaType === 'tv'" label="季" :span="2">
        {{ form.season != null ? form.season : '未指定'}}
        <a-button shape="round" size="small" @click="toSetSeason">
          指定
        </a-button>
      </a-descriptions-item>
      <a-descriptions-item label="自动链接" :span="2">
        {{form.autoLink?'是':'否'}} | {{form.libraryName}} / {{form.toLink}}
      </a-descriptions-item>
      <a-descriptions-item label="下载器" :span="2">
        {{form.clientName}}
      </a-descriptions-item>
      <a-descriptions-item label="HASH" :span="2">
        {{form.hashString}}
      </a-descriptions-item>
    </a-descriptions>
    <a-divider orientation="left" class="extra-title">下载信息
      <a-spin :spinning="loading" size="small" :style="{marginLeft: '5px'}" />
    </a-divider>
    <a-empty v-if="form.status !== 'linked'" :image="emptyImage">
      <template #description>
        <span>
          还未推送到下载器
        </span>
      </template>
      <a-button type="primary" @click="toPush">推 送</a-button>
    </a-empty>
    <template v-else>
      <a-alert v-if="info.errorString" :message="info.errorString" type="error" show-icon />
      <a-empty v-if="!info.id" :image="emptyImage">
        <template #description>
          <span>
            数据加载失败
          </span>
        </template>
        <a-button type="primary" @click="loadInfoInClient">
          <template #icon>
            <ReloadOutlined />
          </template>
          刷 新
        </a-button>
      </a-empty>
      <template v-else>
        <a-row :gutter="10">
          <a-col span="8">
            <a-button size="small" @click="doAction('start')" :loading="doActioning" block>
              <template #icon>
                <PlayCircleOutlined />
              </template>
              开 始
            </a-button>
          </a-col>
          <a-col span="8">
            <a-button type="warning" size="small" @click="doAction('stop')" :loading="doActioning" block>
              <template #icon>
                <PauseCircleOutlined />
              </template>
              停 止
            </a-button>
          </a-col>
          <a-col span="8">
            <a-button type="primary" size="small" @click="loadInfoInClient" block>
              <template #icon>
                <ReloadOutlined />
              </template>
              刷 新
            </a-button>
          </a-col>
        </a-row>
        <a-descriptions :column="2" layout="" :bordered="true" size="small"
          :labelStyle="{width:'100px', textAlign: 'right'}" style="margin: 10px 0 10px 0;">
          <a-descriptions-item label="下载器" :span="2">
            {{ info.client.type }} - {{ info.client.address }}
          </a-descriptions-item>
          <a-descriptions-item label="添加时间" :span="2">
            {{ formatDate(parseInt(info.addedDate)*1000) }}
          </a-descriptions-item>
          <a-descriptions-item label="ID" :span="2">
            {{ info.id }}
          </a-descriptions-item>
          <a-descriptions-item label="名称" :span="2">
            {{ info.name }}
          </a-descriptions-item>
          <a-descriptions-item label="HASH" :span="2">
            {{ info.hashString }}
          </a-descriptions-item>
          <a-descriptions-item label="下载位置" :span="2">
            {{ info.downloadDir }}
          </a-descriptions-item>
          <a-descriptions-item label="已完成" :span="2">
            {{formatSize(info.totalSize - info.leftUntilDone)}}({{ calRatio(info.totalSize -
            info.leftUntilDone, info.totalSize) }}) / {{ formatSize(info.totalSize) }}
          </a-descriptions-item>
          <a-descriptions-item label="状态" :span="2">
            {{ info.status }} |
            <CaretDownOutlined />{{ formatSize(info.rateDownload) }}/s |
            <CaretUpOutlined />{{ formatSize(info.rateUpload) }}/s
          </a-descriptions-item>
        </a-descriptions>
        <p>
          <a-button type="primary" @click="toLink" size="small" block>
            链接或移动到新的位置
          </a-button>
        </p>
        <p>
          <a-button @click="toSetLocation" size="small" block danger>
            修改下载位置
          </a-button>
        </p>

      </template>
    </template>
  </a-drawer>

  <!-- 推送信息确认 -->
  <a-modal v-model:visible="pushShow" title="推送到下载器" okText="推送" @ok="doPush" :confirmLoading="pushLoading">
    <a-form ref="pushForm" :model="pushForm" :rule="pushRules" :label-col="labelCol" :wrapper-col="wrapperCol">
      <a-form-item label="下载器" name="clientid">
        <a-select v-model:value="pushForm.clientid">
          <a-select-option v-for="option in clientOptions" :key="option.id" :value="option.id">
            {{ option.name }}
          </a-select-option>
        </a-select>
      </a-form-item>
      <a-form-item label="是否开始" name="startNow">
        <a-switch v-model:checked="pushForm.startNow" />
      </a-form-item>
      <a-form-item label="启用目录">
        <a-checkbox v-model:checked="pushForm.enableSiteFolder">站点目录</a-checkbox>
        <a-checkbox v-model:checked="pushForm.enableCategoryFolder">分类目录</a-checkbox>
      </a-form-item>
    </a-form>
  </a-modal>

  <!-- 变更下载位置确认 -->
  <a-modal v-model:visible="setLocationShow" title="变更下载位置" okText="变更" @ok="doSetLocation"
    :confirmLoading="setLocationLoading">
    <a-alert :show-icon="false" message="请务必确认新的位置是正确的。" />
    <a-form ref="setLocationForm" :model="setLocationForm" :rule="setLocationRules" :label-col="labelCol"
      :wrapper-col="wrapperCol">
      <a-form-item label="旧的位置">
        <span v-text="setLocationForm.olocation" />
      </a-form-item>
      <a-form-item label="新的位置" name="location">
        <a-input v-model:value="setLocationForm.location" />
      </a-form-item>
      <!-- <a-form-item label="移动文件" name="move">
        <a-switch v-model:checked="setLocationForm.move" />
      </a-form-item> -->
      <a-form-item label="进行校验" name="verify">
        <a-switch v-model:checked="setLocationForm.verify" />
      </a-form-item>
    </a-form>
  </a-modal>

  <!-- 链接到新的位置-->
  <a-drawer height="100%" placement="top" v-model:visible="linkShow" :closable="true" @close="linkClose">
    <a-alert message="说明：" type="info" show-icon>
      <template v-slot:icon>
        <smile-outlined />
      </template>
      <template #description>
        <div>1.种子所在下载器与本系统部署在同一服务器；</div>
        <div>2.确认已配置无误：下载器-下载目录映射；</div>
        <div>3.慎用移动功能，将移动下载文件，影响做种；</div>
        <div>4.目前每次执行硬链接或移动都是本次的执行结果，不会保留之前的执行结果。</div>
      </template>
    </a-alert>
    <a-spin tip="处理中..." :spinning="linking">
      <a-row class="link-op-row">
        <a-col :span="12">
          <a-input addon-before="原本目录：" v-model:value="linkInfo.sourceDir" disabled />
        </a-col>
      </a-row>
      <a-row class="link-op-row">
        <a-col :span="12">
          <a-input-group compact>
            <a-input addon-before="目标目录：" v-model:value="linkInfo.linkDir">
              <template #suffix>
                <FolderOpenOutlined @click="folderSelectShow=true" />
              </template>
            </a-input>
          </a-input-group>
        </a-col>
      </a-row>
      <a-row class="link-op-row">
        <a-col :span="12">
          <a-input-group compact>
            <a-input addonBefore="将" v-model:value="replaceFrom" placeholder="" allowClear />
            <a-input-search addonBefore="替换为" v-model:value="replaceTo" placeholder="" @search="doReplace" allowClear>
              <template v-slot:enterButton>
                <a-button type="primary">
                  文件名替换
                </a-button>
              </template>
            </a-input-search>
          </a-input-group>
        </a-col>
      </a-row>
      <a-row class="link-op-row">
        <a-col :span="24">
          <a-space>
            <a-button type="primary" :loading="linking" @click="doLink(false)">
              硬链接
            </a-button>
            <a-button type="danger" :loading="linking" @click="toMove">
              移动
            </a-button>
          </a-space>
        </a-col>
      </a-row>
      <a-row class="link-op-row">
        <a-col :span="24">
          <p style="margin:1em 0 0 0;">已选择 {{selectedLinkRowKeys.length}} 条，共 {{linkRows.length}} 条</p>
        </a-col>
      </a-row>
      <a-table bordered :data-source="linkRows" :columns="linkRowsCols" rowKey="idx" :loading="linkInfoLoading"
        :row-selection="{ selectedRowKeys: selectedLinkRowKeys, onChange: onSelectLinkChange }" :pagination="false"
        size="small">
        <template #bodyCell="{ column, record}">
          <template v-if="column.key === 'ratioCompleted'">
            {{ formatSize(record.bytesCompleted) }}({{ calRatio(record.bytesCompleted, record.length) }})
          </template>
          <template v-else-if="column.key === 'linkFile'">
            <a-input v-model:value="record.linkFile">
              <template #suffix>
                <a-tooltip title="恢复为原文件名">
                  <UndoOutlined @click="record.linkFile = record.sourceFile" />
                </a-tooltip>
              </template>
            </a-input>
          </template>
          <template v-else-if="column.key === 'replace'">
            <a-switch checked-children="覆盖" un-checked-children="忽略" v-model:checked="record.replace" />
          </template>
          <template v-else-if="column.key === 'status'">
            {{ linkRowStatus(record.status) }}
          </template>
        </template>
      </a-table>
    </a-spin>
  </a-drawer>
  <!-- 路径选择 -->
  <a-modal v-model:visible="folderSelectShow" title="选择目录" @ok="linkDirChange">
    <FileSelector ref="refFileSelector" />
  </a-modal>
  <!-- 媒体信息识别 -->
  <a-drawer height="100%" placement="top" v-model:visible="recognizeShow" :closable="true" @close="recognizeShow=false">
    <Recognize :id="form.id" @close="recognizeFinish" />
  </a-drawer>



  <!-- 指定季数 -->
  <a-modal v-model:visible="seasonSelectShow" title="指定季数" okText="确定" @ok="setSeasonFinish">
    <a-alert :show-icon="false" message="未指定季数将从媒体文件名解析获取。" />
    <a-form ref="setSeasonForm" :model="setSeasonForm" :label-col="labelCol" :wrapper-col="wrapperCol">
      <a-form-item label="季数">
        <a-select v-model:value="setSeasonForm.season" placeholder="请选择季数">
          <a-select-option v-for="option in seasonSelectOptions" :value="option.value">{{option.text}}</a-select-option>
        </a-select>
      </a-form-item>
    </a-form>
  </a-modal>

</template>

<script>
import CommonUtil from '../../utils/CommonUtil.js'
import { downloadFile } from '../../utils/DownloadUtil'
import api from '../../api/api.js'
import TorrentApi from '../../api/TorrentApi.js'
import MediaApi from '@/api/MediaApi';
import { ReloadOutlined, SmileOutlined, PauseCircleOutlined, PlayCircleOutlined, FolderOpenOutlined, UndoOutlined, DownloadOutlined, CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons-vue'
import { Modal, Empty } from 'ant-design-vue';
import FileSelector from '../components/FileSelector.vue'
import Recognize from './Recognize.vue'
import { ref } from 'vue';
export default {
  name: 'TorrentDetail',
  components: {
    FileSelector, Recognize,
    ReloadOutlined,
    SmileOutlined,
    PauseCircleOutlined,
    PlayCircleOutlined,
    FolderOpenOutlined,
    UndoOutlined,
    DownloadOutlined,
    CaretDownOutlined,
    CaretUpOutlined
  },
  props: {
    siteOptions: {
      type: Array,
      default: []
    },
    categoryOptions: {
      type: Array,
      default: []
    },
    clientOptions: {
      type: Array,
      default: []
    },
    libraryOptions: {
      type: Array,
      default: []
    },
  },
  setup() {
    const refFileSelector = ref()
    const folderSelected = () => {
      return refFileSelector.value.selectedKeys
    }
    return {
      refFileSelector, folderSelected
    }
  },
  data() {
    return {
      module: 'torrent',
      isShow: false, loading: false, activeKey: ['1'],
      form: {
      },
      statusLabel: {
        "-1": "All",
        "0": "Stopped",
        "1": "Check waiting",
        "2": "Checking",
        "3": "Download waiting",
        "4": "Downloading",
        "5": "Seed waiting",
        "6": "Seeding",
      },
      autoRefresh: null,
      emptyImage: Empty.PRESENTED_IMAGE_SIMPLE,
      info: {
        client: {}
      },
      labelCol: { span: 5 },
      wrapperCol: { span: 19 },
      pushShow: false, pushLoading: false,
      pushForm: {},
      pushRules: {
        clientid: [
          { required: true, message: '请选择下载器', trigger: 'change' },
        ],
      },
      setLocationShow: false, setLocationLoading: false,
      setLocationForm: {},
      setLocationRules: {
        location: [
          { required: true, message: '请填写新的位置', trigger: 'blur' },
        ],
      },
      linkShow: false, linking: false,
      linkInfo: {}, linkInfoLoading: false, folderSelectShow: false,
      linkRows: [], selectedLinkRowKeys: [],
      linkRowsCols: [
        {
          title: '序号',
          fixed: 'left',
          width: 80,
          customRender: ({ index }) => `${index + 1}`,
        },
        {
          title: '已下载',
          key: 'ratioCompleted',
          width: 200,
        },
        {
          title: '文件名（可以包含路径）',
          key: 'linkFile',
        },
        {
          title: '如目标存在',
          key: 'replace',
          width: 100,
          align: 'center',
        },
        {
          title: '状态',
          key: 'status',
          fixed: 'right',
          width: 200,
        },
      ],
      linkFolder: '', replaceFrom: '', replaceTo: '',
      downloading: false, doActioning: false,
      recognizeShow: false,
      seasonSelectShow: false, seasonSelectOptions: [], setSeasonForm: {}
    }
  },
  methods: {
    formatDate(val) {
      return CommonUtil.formatTimestamp(val)
    },
    calRatio(a, total) {
      let temp = a / total * 100
      return temp.toFixed(2) + '%'
    },
    formatSize(val) {
      let temp = parseFloat(val) // byte
      if (temp < 1024) return temp.toFixed(2) + "B"
      temp = temp / 1024  //kb
      if (temp < 1024) return temp.toFixed(2) + "KB"
      temp = temp / 1024 //mb
      if (temp < 1024) return temp.toFixed(2) + "MB"
      temp = temp / 1024 //gb
      if (temp < 1024) return temp.toFixed(2) + "GB"
      temp = temp / 1024 //tb
      if (temp < 1024) return temp.toFixed(2) + "TB"
      temp = temp / 1024 //pb
      return temp.toFixed(2) + "PB"
    },
    open(form) {
      this.pushForm = {
        id: '',
        clientid: '',
        startNow: false,
      }
      this.form = form
      this.info = {
        client: {}
      }
      this.loadInfoInClient()
      this.isShow = true
      // this.startAutoRefresh()
    },
    onClose() {
      // this.activeKey = []
      this.stopAutoRefresh()
    },
    startAutoRefresh() {
      if (this.autoRefresh) return
      this.autoRefresh = setInterval(() => {
        this.loadInfoInClient()
      }, 5000);
    },
    stopAutoRefresh() {
      if (!this.autoRefresh) return
      clearInterval(this.autoRefresh)
      this.autoRefresh = null
    },
    loadInfoInClient() {
      if (this.form.status !== 'linked') return
      this.loading = true
      TorrentApi.infoInClient({ id: this.form.id }).then(response => {
        if (response.data.code === 1) {
          if (response.data.data)
            this.info = response.data.data
        } else {
          this.stopAutoRefresh()
          this.$message.error(`数据加载失败：${response.data.message}`)
        }
      }).then(() => {
        this.loading = false
      })
    },
    async downloadTorrentFile(file) {
      this.downloading = true
      const downloadObj = await api.download({ name: file, type: 'torrent' });
      this.downloading = false
      // console.log(downloadObj)
      downloadFile(downloadObj.data, file)
    },
    toPush() {
      this.pushForm.id = this.form.id
      this.pushForm.clientid = this.form.clientid
      this.pushForm.startNow = false
      this.pushForm.enableSiteFolder = false
      this.pushForm.enableCategoryFolder = true
      this.pushShow = true
    },
    doPush() {
      this.$refs.pushForm
        .validate()
        .then(() => {
          this.pushLoading = true
          TorrentApi.pushToClient(this.pushForm).then(response => {
            if (response.data.code === 1) {
              this.form.hashString = response.data.data.hashString
              // this.info = response.data.data
              this.loadInfoInClient()
              this.pushShow = false
              this.$message.success('推送成功')
            } else {
              this.$message.error(`推送失败：${response.data.message}`)
            }
          }).catch((error) => {
            this.$message.error(`推送失败：${error.message}`)
          }).then(() => {
            this.pushLoading = false
          })
        })
        .catch(error => {
          // console.log('error', error);
        })
    },
    linkClose() {
      this.linkInfo = {}
      this.linkRows = [],
        this.selectedLinkRowKeys = []
      this.linkFolder = ''
      this.replaceFrom = ''
      this.replaceTo = ''
    },
    toLink() {
      this.linkShow = true
      if (this.linking || this.linkInfoLoading) return // 正在处理
      this.linkInfoLoading = true
      TorrentApi.linkToLibrary({ id: this.form.id }).then(response => {
        if (response.data.code === 1) {
          this.linkInfo.torrentId = this.form.id,
            this.linkInfo.sourceDir = response.data.data.sourceDir
          this.linkRows = response.data.data.files.map((file, index) => {
            return {
              idx: index,
              sourceFile: file.name,
              linkFile: file.name,
              bytesCompleted: file.bytesCompleted,
              length: file.length,
              replace: false,
              status: 0
            }
          })
        } else {
          this.$message.error(`${response.data.message}`)
        }
      }).then(() => {
        this.linkInfoLoading = false
      })
    },
    linkRowStatus(status) {
      if (status === 0)
        return '未执行'
      else if (status === 1)
        return '成功'
      else if (status === 201)
        return '原文件不存在'
      else if (status === 202)
        return '目标文件已存在'
      else
        return '未知'
    },
    doReplace() {
      if (this.replaceFrom) {
        this.linkRows.forEach(r => {
          r.linkFile = r.linkFile.replace(this.replaceFrom, this.replaceTo)
        })
      }
    },
    onSelectLinkChange(selectedRowKeys) {
      // console.log('selectedRowKeys changed: ', selectedRowKeys);
      this.selectedLinkRowKeys = selectedRowKeys;
    },
    linkDirChange() {
      this.linkInfo.linkDir = this.folderSelected()[0]
      this.folderSelectShow = false
    },
    toMove() {
      const that = this
      Modal.confirm({
        title: '请确认自己在做什么',
        content: '移动文件会影响做种！移动前会自动暂停种子。',
        okText: '继续',
        cancelText: '取消',
        onOk() {
          that.doLink(true)
        }
      });
    },
    doLink(move) {
      this.linking = true
      if (!this.linkInfo.linkDir) {
        this.$message.warn("请指定目标目录")
        this.linking = false
        return
      }
      if (this.selectedLinkRowKeys.length === 0) {
        this.linking = false
        this.$message.warn("请选择需要操作的文件")
        return
      }
      // 哪些需要进行链接
      this.linkRows.forEach(linkRow => {
        linkRow.selected = false
        linkRow.status = 0
      })
      this.selectedLinkRowKeys.forEach(index => {
        this.linkRows[index].selected = true
      })
      // 开始
      TorrentApi.doLinkToLibrary(
        {
          ...this.linkInfo,
          linkRows: this.linkRows,
          move: move
        }
      ).then(response => {
        if (response.data.code === 1) {
          this.linkRows = response.data.data
          this.$message.success('操作完成，执行结果请查看列表')
        } else {
          this.$message.error(`操作失败：${response.data.message}`)
        }
      }).catch((error) => {
        this.$message.error(`操作失败：${error.message}`)
      }).then(() => {
        this.linking = false
      })
    },
    toSetLocation() {
      const site = this.siteOptions.find(o => o.id === this.form.siteid)
      const category = this.categoryOptions.find(o => o.id === this.form.categoryid)
      this.setLocationForm.id = this.form.id
      this.setLocationForm.olocation = this.info.downloadDir
      this.setLocationForm.location = this.info.baseDownlaodPath + (site ? '/' + site.folder : '') + (category ? '/' + category.folder : '')
      this.setLocationForm.move = true
      this.setLocationForm.verify = true
      this.setLocationShow = true
    },
    doSetLocation() {
      this.$refs.setLocationForm
        .validate()
        .then(() => {
          this.setLocationLoading = true
          TorrentApi.setLocation(this.setLocationForm).then(response => {
            if (response.data.code === 1) {
              this.loadInfoInClient()
              this.setLocationShow = false
              this.$message.success('变更成功')
            } else {
              this.$message.error(`变更失败：${response.data.message}`)
            }
          }).catch((error) => {
            this.$message.error(`变更失败：${error.message}`)
          }).then(() => {
            this.setLocationLoading = false
          })
        })
        .catch(error => {
          // console.log('error', error);
        })
    },
    doAction(action) {
      if (!this.form.id && !action) return
      this.doActioning = true
      TorrentApi.doAction(this.form.id, action).then(response => {
        if (response.data.code === 1) {
          setTimeout(() => {
            this.loadInfoInClient()
            this.$message.success('操作成功')
            this.doActioning = false
          }, 3000)
        } else {
          this.doActioning = false
          this.$message.error(`操作失败：${response.data.message}`)
        }
      }).catch((error) => {
        this.doActioning = false
        this.$message.error(`操作失败：${error.message}`)
      })
    },
    toRecognize() {
      this.recognizeShow = true
    },
    recognizeFinish(tmdbInfo) {
      tmdbInfo && (this.form.tmdbid = tmdbInfo.id)
      this.recognizeShow = false
    },
    async toSetSeason() {
      this.setSeasonForm.id = this.form.id
      this.setSeasonForm.season = undefined
      this.seasonSelectOptions = []
      const response = await MediaApi.getByTmdbid({ tmdbid: this.form.tmdbid, type: 'tv' })
      if (response.data.code === 1) {
        if (response.data.data && response.data.data.info) {
          const mediaInfo = JSON.parse(response.data.data.info)
          if (mediaInfo.seasons) {
            this.seasonSelectOptions = mediaInfo.seasons.map(season => {
              return {
                text: `${season.season_number} - ${season.name}`,
                value: season.season_number,
              }
            })
          }
        }
      }
      this.seasonSelectShow = true
    },
    setSeasonFinish() {
      api.update(this.module, this.setSeasonForm).then(response => {
        if (response.data.code === 1) {
          this.form.season = this.setSeasonForm.season
          this.$message.success('操作成功')
        } else {
          this.$message.error(`操作失败：${response.data.message}`)
        }
      }).catch((error) => {
        this.$message.error(`操作失败：${error.message}`)
      }).then(() => {
      this.seasonSelectShow  = false
      })
    }
  }
}
</script>
<style scoped>
.no-wrap {
  overflow-wrap: anywhere;
  margin: 0px;
}

.extra-title {
  color: gray;
  font-size: 14px;
  font-weight: 300;
}

.link-op-row {
  margin: 10px 0;
}
</style>>